﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UniRlv.Utility
{
    [Serializable]
    public class MyList<T>:IList<T>
    {
        List<T> lst1 = new List<T>(200000);
        List<T> lst2 = new List<T>(200000);
        List<T> lstMerge = new List<T>();
        public bool bMergeOne { get; set; }//一级码是否两道采集
       

        public int IndexOf(T item)
        {
            int idx = lst1.IndexOf(item);

            if (bMergeOne)
            {
                if (idx >= 0)
                {
                    return idx * 2;
                }

                idx = lst2.IndexOf(item);

                if (idx >= 0)
                {
                    return idx * 2 + 1;
                }

                return -1;
            }
            else
            {
                return idx;
            }
        }

        public int GetCount(int line)
        {
            if (bMergeOne)
            {
                if (line == 0)
                {
                    return lst1.Count;
                }
                else
                {
                    return lst2.Count;
                }
            }
            else
            {
                return lst1.Count+lst2.Count;
            }
        }

        public T GetTop(int line)
        {
            if (bMergeOne)
            {
                if (line == 0)
                {
                    return lst1[lst1.Count-1];
                }
                else
                {
                    return lst2[lst2.Count - 1];
                }
            }
            else
            {
                return lst1[lst1.Count-1];
            }
        }

        public void Insert(int index, T item)
        {
            if (bMergeOne)
            {
                try
                {
                    if (index % 2 == 0)
                    {
                        lst1.Insert(index / 2, item);
                    }
                    else
                    {
                        lst2.Insert(index / 2, item);
                    }
                }
                catch (Exception)
                {

                }

            }
            else
            {
                lst1.Insert(index, item);
            }
            
        }

        public void RemoveAt(int index)
        {

                if (bMergeOne)
                {
                    try
                    {
                        if (index % 2 == 0)
                        {
                            lst1.RemoveAt(index / 2);
                        }
                        else
                        {
                            lst2.RemoveAt(index / 2);
                        }
                                
                    }
                    catch (Exception)
                    {
                    }
                }
                else
                {
                    lst1.RemoveAt(index);
                }

        }

        public T this[int index]
        {
            get
            {
                if (bMergeOne)
                {//有可能出现双通道数量不一样，所以访问尾元素时须先合并两个通道
                    if (index % 2 == 0)
                    {
                        if (index / 2 >= lst1.Count || index / 2 >= lst2.Count)
                        {
                            return MergeList()[index];
                        }
                        else
                        {
                            return lst1[index / 2];
                        }
                        
                    }
                    else
                    {
                        if (index / 2 >= lst1.Count || index / 2 >= lst2.Count)
                        {
                            return MergeList()[index];
                        }
                        else
                        {
                            return lst2[index / 2];
                        }
                    }
                }
                else
                {
                    return lst1[index];
                }

            }
            set
            {
                if (bMergeOne)
                {
                    if (index % 2 == 0)
                    {
                        lst1[index / 2] = value;
                    }
                    else
                    {
                        lst2[index / 2] = value;
                    }
                }
                else
                {
                    lst1[index] = value;
                }

            }
        }

        public void Add(int line, T item)
        {
            if (bMergeOne)
            {
                if (line == 0)
                {
                    lst1.Add(item);
                }
                else
                {
                    lst2.Add(item);
                }
            }
            else
            {
                lst1.Add(item);
            }
        }

        public void Clear()
        {
            lst1.Clear();
            lst2.Clear();
        }

        public bool Contains(T item)
        {
            return lst1.Contains(item) || lst2.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            lst1.CopyTo(array, arrayIndex);
        }

        public void CopyTo1(T[] array, int arrayIndex)
        {
            lst1.CopyTo(array, arrayIndex);
        }

        public void CopyTo2(T[] array, int arrayIndex)
        {
            lst2.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return lst1.Count + lst2.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(T item)
        {
            
            if (lst1.Remove(item))
            {
                return true;
            }

            if (lst2.Remove(item))
            {
                return true;
            }

            return false;
        }

        public void AddRange(MyList<T> ml)
        {
            lst1.AddRange(ml.lst1);
            lst2.AddRange(ml.lst2);
        }

        public void AddRange1(IEnumerable<T> il)
        {
            lst1.AddRange(il);
        }

        public void AddRange2(IEnumerable<T> il)
        {
            lst2.AddRange(il);
        }

        /// <summary>
        /// 自定义的批量删除方法，用于通过父码位置删除对应包装内子码
        /// </summary>
        /// <param name="index">删除位置</param>
        /// <param name="ratio">比例系数</param>
        public void RemoveRange(int index, int ratio)
        {
            if (bMergeOne)
            {

                int range = ratio / 2;
                for (int i = range * (index + 1); i > range * index; i--)
                {
                    try
                    {
                        lst1.RemoveAt(i - 1);
                    }
                    catch (Exception)
                    {
                    }
                        
                }

                for (int i = range * (index + 1); i > range * index; i--)
                {
                    try
                    {
                        lst2.RemoveAt(i - 1);
                    }
                    catch (Exception)
                    {
                    }
                }

            }
            else
            {
                for (int i = ratio * (index + 1); i > ratio * index; i--)
                {
                    lst1.RemoveAt(i - 1);
                }
            }

        }

        public IEnumerable<T> FindRange(int idx, int cnt)
        {
            return MergeList().Skip(idx).Take(cnt);
        }

        public T FindLast(Predicate<T> match)
        {
            T t = lst1.FindLast(match);

            if (t==null)
            {
                return lst2.FindLast(match);
            }
            else
            {
                return t;
            }
        }

        /// <summary>
        /// 自定义的对象转换方法，用于将码对象转换为24位码
        /// </summary>
        /// <typeparam name="TOutput"></typeparam>
        /// <param name="converter"></param>
        /// <returns></returns>
        public List<TOutput> MyConvertAll<TOutput>(Converter<T, TOutput> converter)
        {
            return MergeList().ConvertAll(converter);
        }

        public IEnumerator<T> GetEnumerator()
        {
            return MergeList().GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return MergeList().GetEnumerator();
        }

        public List<T> FindAll(Predicate<T> match)
        {
            return lst1.FindAll(match).Concat(lst2.FindAll(match)).ToList();
        }

        private List<T> MergeList()
        {
            
            if (bMergeOne)
            {
                int cnt;
                lstMerge.Clear();

                if (lst1.Count > lst2.Count)
                {
                    cnt = lst2.Count;
                    for (int i = 0; i < cnt; i++)
                    {

                        lstMerge.Add(lst1[i]);
                        lstMerge.Add(lst2[i]);
                    }

                    int loop = (lst1.Count - cnt) / 2;

                    for (int i = 0; i < loop; i++)
                    {
                        lstMerge.Add(lst1[cnt + i]);
                        lstMerge.Add(lst1[cnt + loop + i]);
                    }

                    if ((lst1.Count - cnt) % 2 == 1)
                    {
                        lstMerge.Add(lst1[lst1.Count - 1]);
                    }
                }
                else
                {
                    cnt = lst1.Count;
                    for (int i = 0; i < cnt; i++)
                    {

                        lstMerge.Add(lst1[i]);
                        lstMerge.Add(lst2[i]);
                    }

                    int loop = (lst2.Count - cnt) / 2;

                    for (int i = 0; i < loop; i++)
                    {
                        lstMerge.Add(lst2[cnt + i]);
                        lstMerge.Add(lst2[cnt + loop + i]);
                    }

                    if ((lst2.Count - cnt) % 2 == 1)
                    {
                        lstMerge.Add(lst2[lst2.Count - 1]);
                    }
                }

                return lstMerge;
            }
            else
            {
                return lst1;
            }
        }

        public void Add(T item)
        {
            lst1.Add(item);
        }

        public List<T> GetList(int line)
        {

            if (line == 0)
            {
                return lst1;
            }
            else
            {
                return lst2;
            }
        }
    }
}
